package com.netty.common;

import java.net.InetSocketAddress;

import org.springframework.stereotype.Component;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.ImmediateEventExecutor;

@Component
public class ChatServer {
	private final ChannelGroup channelGroup = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
	private final EventLoopGroup bossGroup = new NioEventLoopGroup();
	private final EventLoopGroup workGroup = new NioEventLoopGroup();
	private Channel channel;
	
	public ChannelFuture start(InetSocketAddress address) {
		ServerBootstrap bootstrap = new ServerBootstrap();
		bootstrap.group(bossGroup, workGroup)//Boss的Reactor有一个线程，而Worker的线程数由Worker线程池大小决定，但是默认最大不会超过CPU核数*2
				//指定使用NioServerSocketChannel产生一个Channel用来接收连接
				.channel(NioServerSocketChannel.class)
				//ChannelInitializer用于配置一个新的Channel
				//用于向你的Channel当中添加ChannelInboundHandler的实现
				.childHandler(new ChatServerInitializer(channelGroup))
				//以下是socket的标准参数
				//BACKLOG用于构造服务端套接字ServerSocket对象，标识当服务器请求处理线程全满时，用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1，Java将使用默认值50。
				//Option是为了NioServerSocketChannel设置的，用来接收传入连接的
				.option(ChannelOption.SO_BACKLOG, 128)
				//是否启用心跳保活机制。在双方TCP套接字建立连接后（即都进入ESTABLISHED状态）并且在两个小时左右上层没有任何数据传输的情况下，这套机制才会被激活。
				//childOption是用来给父级ServerChannel之下的Channels设置参数的
				.childOption(ChannelOption.SO_KEEPALIVE, true);
		// Bind and start to accept incoming connections
		ChannelFuture future = bootstrap.bind(address).syncUninterruptibly();
		channel = future.channel();
		return future;
	}
	
	public void destroy() {
		if(channel != null) {
			channel.close();
		}
		
		channelGroup.close();
		workGroup.shutdownGracefully();
		bossGroup.shutdownGracefully();
	}
	
/*	public static void main(String[] args) {
		ChatServer server = new ChatServer();
		InetSocketAddress address = new InetSocketAddress("127.0.0.1", 9999);
		ChannelFuture future = server.start(address);
		
		Runtime.getRuntime().addShutdownHook(new Thread(){
			@Override
			public void run() {
				server.destroy();
			}
		});
		
		future.channel().closeFuture().syncUninterruptibly();
	}*/
}
